iT邦幫忙

DAY 5
3

用python擷取網頁上的開放資訊(數據資料),分析及畫出圖表系列 第 5

用python抓網頁data,及做圖表之五:抓網頁內建庫urllib及第三方庫BeautifulSoup的使用

  • 分享至 

  • xImage
  •  

筆者用urllib抓網頁,urllib在python2/3版本的差異頗大,有些是傳回值的型別不一樣,有些是方法,成員改寫掉了,
本文是用python3的版本。
抓網頁中的table裏的td欄位裏的值,筆者是用知名的BeautifulSoup庫來進行
營收報表受IFRS影響,
所以2013(102)年沒法用同一個網址來擷取data,
iInfo先生分享的程式,只需要做一個微小的改變。
不過,筆者用此來做個不同庫的DEMO, 可以做個比較。

http://mops.twse.com.tw/mops/web/index公開資訊觀測站的
位置:
彙總報表/資訊揭露/每月營收/採用IFRSs前營業收入匯總表/每月營業收入統計彙總表
102年後資料請至採用IFRSs後營業收入彙總查詢。

當你Key入102年,會出現:
102年後資料請至採用IFRSs營業收入彙總查詢。

所以要去:採用IFRSs營業收入匯總表,抓取資料。
我們試抓1,2,8月來觀察網址(URL)的規律:
http://mops.twse.com.tw/t21/sii/t21sc03_102_1_0.html
http://mops.twse.com.tw/t21/sii/t21sc03_102_2_0.html
http://mops.twse.com.tw/t21/sii/t21sc03_102_8_0.html
看一下
採用IFRSs營業收入匯總表的網址,
http://mops.twse.com.tw/t21/sii/t21sc03_101_8.html
所以只要把
iInfo先生分享的程式,

 url = "http://mops.twse.com.tw/t21/" + stocktype + "/t21sc03_" + pyROCYear 
+ "_" + str(k) + ".html"

改成

 url = "http://mops.twse.com.tw/t21/" + stocktype + "/t21sc03_" + pyROCYear 
+ "_" + str(k) + "_0.html"

只差在**_0**。
-------------------------------------------
那就開始練習urllib+BeautifulSoup
進入練習之前:

可以了解有很多個table, 我們要擷取的data就在眾多個table裏。
練習一:藉由urllib.request庫把網頁整個抓回來,並轉給BeautifulSoup,記得要decode('cp950')

import urllib.request
from bs4 import BeautifulSoup
url = 'http://mops.twse.com.tw/t21/sii/t21sc03_102_1_0.html'
response = urllib.request.urlopen(url)
html = response.read()
sp = BeautifulSoup(html.decode('cp950')) 
sp

練習二:把多個table找出來

tbls=sp.find_all('table', attrs={ 'width' : "100%" })
tbls
tbls[0]
tbls[1]

練習三:換找table的屬性,上一練習找到不需要的table, 多個屬性時,用字典(Dictionaries)型別來表示,字典型別對筆者來說,算是不太習慣,在這裏,key/value, 是非常恰當的用途!

tblh=sp.find_all('table', attrs={ 'border' : '0','width' : '100%' })
tblh[0]

在語義上,可以發現find_all,find的差異,非常直覺
練習四:發現要抓取的data裏是,table裏再包一個table

tbl=tblh[0].find('table', attrs={ 'bordercolor' : "#FF6600" })
tbl

練習五:營收數字的table裏,把每一列(tr)抓出來

trs=tbl.find_all('tr')
trs[0],trs[1],trs[2]

看了資料,知道trs[0],trs[1]是中文欄位說明,所以要塞資料庫(sqlite3)時,從第trs[2]開始解析欄位值
練習六:list的長度,用於抓取最後一列

ln=len(trs)
ln
trs[ln-1],trs[ln-2],trs[ln-3]

用len(List)知道這個table裏有幾列(tr),最後一列是ln-1,是合計列,也不用寫入資料庫(sqlite3)
練習七:從每一列裏,得到每一欄(td)值, 做到此,大家都知道用find_all('td')吧

tds=trs[2].find_all('td')
tds[0]
tds[0].get_text(),tds[1].get_text(),tds[2].get_text(),tds[3].get_text(),tds[4].get_text()
output:
('1101', '台泥', '              9,134,465', '不適用', '              7,125,036')

練習八:把數字欄位的空白去掉,千分位,十萬分位的逗點去掉

td2=tds[2].get_text()
td2=td2.strip().replace(",", "")
td2
output:
'9134465'

練習八:把數字欄位裏“不適用”,換成0

td3=tds[3].get_text()
if  td3 == (u'不適用') :
    td3='0'
td3
output:
  if  td3 == (u'不適用') :
            ^
SyntaxError: invalid character in identifier

糗了,真的'不適用'
肚子餓,頭昏,晚一點再找一下解法

**小結:**互動式作業環境,對於解析網頁特別適用,之後再用迴圈把片斷的程式碼,
組合起來,就能批次作業了。


上一篇
用python抓網頁data,及做圖表之四:統計圖的加強,以月營收及月成交資訊為例
下一篇
用python抓網頁data,及做圖表之六:抓102年之後月營收的data,整合練習
系列文
用python擷取網頁上的開放資訊(數據資料),分析及畫出圖表22
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
一級屠豬士
iT邦大師 1 級 ‧ 2013-09-20 14:59:30

這個美麗湯是好東西啊,我也有用他來抓一些美麗的東西.

我要留言

立即登入留言